﻿// ------------------------------------------------------------------------------
// <copyright file="SolidColorBrushConverter.cs" company="skumaronline.com">
//    Copyright (C) 2012 Suresh Kumar T.
//
//    This program is free software; you can redistribute it and/or
//    modify it under the terms of the GNU General Public License
//    as published by the Free Software Foundation version 2
//    of the License.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    http://www.gnu.org/licenses/gpl-2.0.html
//
// </copyright>
// ------------------------------------------------------------------------------

namespace StoreAppLib.Converters
{
    using System;
    using System.Globalization;
    using System.Text.RegularExpressions;
    using Windows.UI;
    using Windows.UI.Xaml;
    using Windows.UI.Xaml.Data;
    using Windows.UI.Xaml.Media;

    /// <summary>
    /// Color to Solid Color Brush converter
    /// </summary>
    public sealed class SolidColorBrushConverter : IValueConverter
    {
        /// <summary>
        /// Concatenate color data during binding to solid brush value
        /// The converter automatically decide the format. It can identify the following formats
        /// Hex decimal: #X2X2X2, #X2X2X2X2, X2X2X2 and X2X2X2X2
        /// Decimal : R,G,B and A,R,G,B
        /// </summary>
        /// <param name="value">The value produced by the binding source.</param>
        /// <param name="targetType">The type of the binding target property.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="language">The culture to use in the converter.</param>
        /// <returns>A converted value. If the method returns null, the valid null value is used.</returns>
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            Color color = Colors.Transparent;

            if (value != null)
            {
                if (value is string)
                {
                    string colorValue = (string)value;

                    if (colorValue.StartsWith("#"))
                    {
                        colorValue = colorValue.Substring(1);
                    }

                    if (Regex.IsMatch(colorValue, @"^[A-Fa-f0-9]{6}$"))
                    {
                        colorValue = "FF" + colorValue;
                    }

                    if (Regex.IsMatch(colorValue, @"^[A-Fa-f0-9]{8}$"))
                    {
                        byte a = (byte)int.Parse(colorValue.Substring(0, 2), NumberStyles.HexNumber);
                        byte r = (byte)int.Parse(colorValue.Substring(2, 2), NumberStyles.HexNumber);
                        byte g = (byte)int.Parse(colorValue.Substring(4, 2), NumberStyles.HexNumber);
                        byte b = (byte)int.Parse(colorValue.Substring(6, 2), NumberStyles.HexNumber);

                        color = ColorHelper.FromArgb(a, r, g, b);
                    }

                    if (Regex.IsMatch(colorValue, @"^(\d+),\s*(\d+),\s*(\d+)$"))
                    {
                        colorValue = "255," + colorValue;
                    }

                    if (Regex.IsMatch(colorValue, @"^(\d+),\s*(\d+),\s*(\d+),\s*(\d+)$"))
                    {
                        byte v;

                        string[] arr = colorValue.Split(',');

                        byte.TryParse(arr[0], out v);
                        byte a = v;
                        byte.TryParse(arr[1], out v);
                        byte r = v;
                        byte.TryParse(arr[2], out v);
                        byte g = v;
                        byte.TryParse(arr[3], out v);
                        byte b = v;

                        color = ColorHelper.FromArgb(a, r, g, b);
                    }
                }
                else if (value is Color)
                {
                    color = (Color)value;
                }
            }

            return new SolidColorBrush(color);
        }

        /// <summary>
        /// Convert color value to string data when propagates the value from the binding target to the binding source.
        /// By default, the format is hex decimal (#X2X2X2X2). You can also specify the following format as parameter.
        /// Hex decimal: #X2X2X2, #X2X2X2X2, X2X2X2 and X2X2X2X2
        /// Decimal : R,G,B and A,R,G,B        
        /// </summary>
        /// <param name="value">The value that is produced by the binding target.</param>
        /// <param name="targetType">The type to convert to.</param>
        /// <param name="parameter">The converter parameter to use.</param>
        /// <param name="language">The culture to use in the converter.</param>
        /// <returns>A converted value. If the method returns null, the valid null value is used.</returns>
        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            if (value == null)
            {
                return DependencyProperty.UnsetValue;
            }

            Color color;

            if (value is SolidColorBrush)
            {
                color = (value as SolidColorBrush).Color;
            }
            
            if (color != null)
            {
                if (parameter == null)
                {
                    return "#" + color.A.ToString("X2") + color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");
                }
                else
                {
                    string format = value.ToString().ToUpper();

                    if (format == "R,G,B")
                    {
                        return string.Format("{0},{1},{2}", color.R, color.G, color.B);
                    }
                    else if (format == "A,R,G,B")
                    {
                        return string.Format("{0},{1},{2},{3}", color.A, color.R, color.G, color.B);
                    }
                    else if (format == "X2X2X2")
                    {
                        return color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");
                    }
                    else if (format == "#X2X2X2")
                    {
                        return "#" + color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");
                    }
                    else if (format == "X2X2X2X2")
                    {
                        return color.A.ToString("X2") + color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");
                    }
                    else 
                    {
                        return "#" + color.A.ToString("X2") + color.R.ToString("X2") + color.G.ToString("X2") + color.B.ToString("X2");
                    }
                }
            }
            else
            {
                return DependencyProperty.UnsetValue;
            }
        }
    }
}
